/**
 * 高级日志配置模块
 * 支持按类型和日期分别记录不同类型的日志
 *
 * @author Legendary API Team
 * @version 2.0.0
 * @since 2024-01-01
 */

const morgan = require('morgan');
const fs = require('fs');
const path = require('path');

// 日志类型定义
const LOG_TYPES = {
    ACCESS: 'access',      // 正常请求日志
    ERROR: 'error',        // 系统错误日志
    CUSTOM: 'custom',      // 自定义错误日志
    DATABASE: 'database',  // 数据库相关日志
    SECURITY: 'security'   // 安全相关日志
};

/**
 * 获取当前日期字符串
 * @returns {string} YYYY-MM-DD 格式的日期
 */
function getCurrentDate() {
    return new Date().toISOString().split('T')[0];
}

/**
 * 获取日志文件路径
 * @param {string} type - 日志类型
 * @param {string} date - 日期 (可选，默认今天)
 * @returns {string} 日志文件完整路径
 */
function getLogFilePath(type, date = getCurrentDate()) {
    const logsDir = path.join(__dirname, '..', 'logs', type);

    // 确保目录存在
    if (!fs.existsSync(logsDir)) {
        fs.mkdirSync(logsDir, { recursive: true });
    }

    return path.join(logsDir, `${date}.log`);
}

/**
 * 写入日志到文件
 * @param {string} type - 日志类型
 * @param {string} message - 日志消息
 * @param {Object} data - 额外数据 (可选)
 */
function writeLog(type, message, data = {}) {
    const timestamp = new Date().toISOString();
    const logPath = getLogFilePath(type);

    // 格式化日志内容
    let logContent = `----------------------------------------
日志类型: ${type}
记录时间: ${timestamp}
日志消息: ${message}
`;

    // 添加额外数据
    if (Object.keys(data).length > 0) {
        logContent += '详细信息:\n';
        Object.entries(data).forEach(([key, value]) => {
            if (typeof value === 'object') {
                logContent += `${key}: ${JSON.stringify(value, null, 2)}\n`;
            } else {
                logContent += `${key}: ${value}\n`;
            }
        });
    }

    logContent += '----------------------------------------\n';

    fs.appendFileSync(logPath, logContent);
}

/**
 * 创建Morgan中间件，记录访问日志
 * @returns {Function} Morgan中间件
 */
function createAccessLogger() {
    console.log('📝 [日志] 访问日志文件: ' + getLogFilePath(LOG_TYPES.ACCESS));
    const logStream = {
        write: (message) => {
            try {
                // 输出到控制台
                console.log(message.trim());
                // 解析Morgan combined格式
                const messageStr = message.trim();
                const regex = /^(\S+) - - \[([^\]]+)\] "(\S+) (\S+) ([^"]+)" (\d+) (\d+) "([^"]*)" "([^"]*)"$/;
                const match = messageStr.match(regex);
                let logContent = '';
                if (match) {
                    const [, remoteAddr, timestamp, method, url, httpVersion, status, responseSize, referer, userAgent] = match;
                    logContent = `----------------------------------------\n访问时间: ${timestamp}\n请求方法: ${method}\n请求地址: ${url}\nHTTP版本: ${httpVersion}\n响应状态: ${status}\n响应大小: ${responseSize} bytes\n客户端IP: ${remoteAddr}\n来源页面: ${referer || '直接访问'}\n用户代理: ${userAgent}\n----------------------------------------\n`;
                } else {
                    logContent = `----------------------------------------\n解析失败，原始消息: ${messageStr}\n----------------------------------------\n`;
                }
                // 直接同步写入文件，保证每次都写入
                fs.appendFileSync(getLogFilePath(LOG_TYPES.ACCESS), logContent);
            } catch (error) {
                console.error('❌ [Morgan] 日志写入错误:', error);
            }
        }
    };
    return morgan('combined', { stream: logStream });
}

/**
 * 错误日志记录器
 * @param {Error} error - 错误对象
 * @param {Object} req - 请求对象
 * @param {string} type - 错误类型 (可选)
 */
function logError(error, req = {}, type = LOG_TYPES.ERROR) {
    const errorData = {
        name: error.name,
        message: error.message,
        stack: error.stack,
        url: req.originalUrl || '',
        method: req.method || '',
        ip: req.ip || req.connection?.remoteAddress || '',
        userAgent: req.get('User-Agent') || '',
        body: req.body || {},
        query: req.query || {},
        params: req.params || {}
    };

    writeLog(type, error.message, errorData);
}

/**
 * 自定义日志记录器
 * @param {string} message - 日志消息
 * @param {Object} data - 额外数据
 * @param {string} type - 日志类型
 */
function logCustom(message, data = {}, type = LOG_TYPES.CUSTOM) {
    writeLog(type, message, {
        ...data,
        timestamp: new Date().toISOString()
    });
}

/**
 * 数据库日志记录器
 * @param {string} operation - 数据库操作
 * @param {Object} data - 操作数据
 * @param {string} status - 操作状态 (success/error)
 */
function logDatabase(operation, data = {}, status = 'success') {
    writeLog(LOG_TYPES.DATABASE, `数据库操作: ${operation}`, {
        operation,
        status,
        ...data,
        timestamp: new Date().toISOString()
    });
}

/**
 * 安全日志记录器
 * @param {string} event - 安全事件
 * @param {Object} data - 事件数据
 */
function logSecurity(event, data = {}) {
    writeLog(LOG_TYPES.SECURITY, `安全事件: ${event}`, {
        event,
        ...data,
        timestamp: new Date().toISOString()
    });
}

/**
 * 获取日志统计信息
 * @param {string} type - 日志类型
 * @param {string} date - 日期 (可选)
 * @returns {Object} 统计信息
 */
function getLogStats(type, date = getCurrentDate()) {
    const logPath = getLogFilePath(type, date);

    if (!fs.existsSync(logPath)) {
        return { count: 0, size: 0, exists: false };
    }

    const stats = fs.statSync(logPath);
    const content = fs.readFileSync(logPath, 'utf8');
    const lines = content.split('\n').filter(line => line.trim());

    return {
        count: lines.length,
        size: stats.size,
        exists: true,
        date
    };
}

/**
 * 清理旧日志文件
 * @param {number} daysToKeep - 保留天数 (默认30天)
 */
function cleanOldLogs(daysToKeep = 30) {
    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - daysToKeep);

    Object.values(LOG_TYPES).forEach(type => {
        const logsDir = path.join(__dirname, '..', 'logs', type);

        if (fs.existsSync(logsDir)) {
            const files = fs.readdirSync(logsDir);

            files.forEach(file => {
                const filePath = path.join(logsDir, file);
                const stats = fs.statSync(filePath);

                if (stats.mtime < cutoffDate) {
                    fs.unlinkSync(filePath);
                    console.log(`🗑️ 删除旧日志文件: ${filePath}`);
                }
            });
        }
    });
}

/**
 * 配置日志系统
 * @param {Object} options - 配置选项
 * @returns {Function} Morgan中间件
 */
function configureLogger(options = {}) {
    const {
        enableFileLog = true,
        enableConsoleLog = true,
        logTypes = Object.values(LOG_TYPES)
    } = options;

    console.log('📝 [日志] 正在配置高级日志系统...');
    console.log(`📝 [日志] 启用的日志类型: ${logTypes.join(', ')}`);

    if (enableFileLog) {
        console.log('📝 [日志] 文件日志已启用');
    }

    if (enableConsoleLog) {
        console.log('📝 [日志] 控制台日志已启用');
    }

    // 返回访问日志中间件
    return createAccessLogger();
}

module.exports = {
    // 日志类型常量
    LOG_TYPES,

    // 主要函数
    configureLogger,
    logError,
    logCustom,
    logDatabase,
    logSecurity,

    // 工具函数
    getLogFilePath,
    getLogStats,
    cleanOldLogs,
    writeLog,

    // 兼容性函数
    getMorganMiddleware: configureLogger
};